package com.maxd.adapter;


import com.maxd.error.ExceptionEnum;
import com.maxd.error.Result;
import com.maxd.error.ResultUtil;
import com.maxd.model.Token;
import com.maxd.model.UserInfo;
import com.maxd.respository.userinfo.UserRepository;
import com.maxd.service.token.ITokenService;
import com.maxd.utils.SeqUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@Slf4j
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private ITokenService userService;
    @Autowired
    private UserRepository userRepository;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        LoginUserHolder.removeUserInfo();
        LoginUserHolder.removeAdminId();
        MDC.put("traceId", SeqUtils.traceId());
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        response.setHeader("Access-Control-Allow-Origin", "*");
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String requestPath = request.getRequestURI();
        // NeedLogin注解表明需要登录，优先级最高
        if(!method.isAnnotationPresent(NeedLogin.class)) {
            if (requestPath.contains("/swagger") || requestPath.contains("/configuration/ui") || requestPath.contains("/v3/api-docs")) {
                return true;
            }
            if (requestPath.contains("/jd") || requestPath.contains("/pdd") || requestPath.contains("/error") || requestPath.contains("/taobao") || requestPath.contains("/wx")) {
                return true;
            }
            if (method.isAnnotationPresent(IgnoreSecurity.class)) {
                return true;
            }
        } else {
            log.info("NeedLogin for url : {}", request.getRequestURI());
        }
        String token = request.getHeader("token");
        log.info("登录拦截，token = {}", token);
        if (token == null || token.isEmpty()) {
            Result error = ResultUtil.error(ExceptionEnum.WRONT_TOKEN);
            log.info("token: " + error);
            throw new Exception("用户信息失效,请重新登录");
        }
        //String userId = userService.getUserByUuid(token);
        Token token1 = userService.getToken(token);
        if (token1 != null) {
            log.info("token found: {}", token1);
            if(token1.getUserId()!=null){
                UserInfo userById = userRepository.getUserById(Long.parseLong(token1.getUserId()));
                if(userById==null || "false".equals(userById.getState())){
                    throw new Exception("用户信息失效,请重新登录");
                }
                LoginUserHolder.setUserInfo(userById);
            }
            request.setAttribute("userId", token1.getUserId()==null?token1.getAdminId():token1.getUserId());
            if(StringUtils.isNotEmpty(token1.getAdminId())) {
                LoginUserHolder.setAdminId(token1.getAdminId());
            }
        } else {
            request.setAttribute("userId", null);
            Result error = ResultUtil.error(ExceptionEnum.WRONT_TOKEN);
            log.info("token: " + error);
            throw new Exception("用户信息失效,请重新登录");
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        LoginUserHolder.removeUserInfo();
        LoginUserHolder.removeAdminId();
        MDC.remove("traceId");
    }
}
